package com.cloud.spider.service.impl;

import com.cloud.spider.clients.PublicCrawlerClient;
import com.cloud.spider.dtos.ChapterContentDto;
import com.cloud.spider.dtos.ChapterLinkDto;
import com.cloud.spider.dtos.CrawlNovelRequestDto;
import com.cloud.spider.dtos.ResponseResult;
import com.cloud.spider.service.PublicCrawlerService;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static com.cloud.spider.constants.CrawlerConstant.RESULT_TYPE_HTML;
import static com.cloud.spider.constants.CrawlerConstant.TRUE;

/**
 * @Description:
 * @ClassName: PublicCrawlerServiceImpl
 * @Package: com.cloud.spider.service.Impl
 * @Author 柳晓宇
 * @Create 2023/10/12 11:29
 * @Version 1.0
 */
@Service
public class PublicCrawlerServiceImpl implements PublicCrawlerService {

    @Autowired
    private PublicCrawlerClient client;

    @Async("spiderThreadPoolExecutor")
    @Override
    public void asyncTest(int i) {
        System.out.println(Thread.currentThread().getName() + "=======================" + i);
    }

    /**
     * <p>
     * 全部设置默认选项 提示没有成功？使用详细配置试试
     * 目录
     * 目录元素一般比较简单，直接解析option或者a标签即可。使用set存放目录链接，不担心重复。
     * 详细设置 用户复制进来，用正则解析标签，排除/ 开头元素
     * <p>
     * 正文
     * 正文内容需要最外层元素
     * 需要排除的内容 让用户连标签一起复制进来
     * 下一页 形式
     * 列表 与分页一样，直接让复制进来
     * 下一页按钮 默认下划线"_"分割。
     *
     *
     * </p>
     */
    @Override
    public ResponseResult parse(CrawlNovelRequestDto dto) {
        // 访问分页目录地址
        String response = client.http(dto.getCatalogueUrl());
        List<ChapterLinkDto> contentLinkList = new ArrayList<>(1024);
        List<ChapterContentDto> chapterContentList = new ArrayList<>(1024);
        // 校验类型
        if (RESULT_TYPE_HTML.equals(dto.getResultType())) {
            Document pageDocument = Jsoup.parse(response);

            //确定分页html范围
            String attribute = dto.getPageAttribute();
            String attributeValue = dto.getPageAttributeValue();
            String select = "div[" + attribute + "='" + attributeValue + "']";

            Element firstPageDocument = pageDocument.select(select).first();

            Elements pageUrisElements = firstPageDocument.select("option");
            List<String> pageUriList = pageUrisElements.stream().map(pageLink -> {
                return pageLink.attr("value");
            }).collect(Collectors.toList());
            System.out.println(pageUriList);

            if (pageUrisElements == null) {
                pageUrisElements = firstPageDocument.select("ul.li a");
                pageUriList = pageUrisElements.stream().map(pageLink -> {
                    return pageLink.attr("href");
                }).collect(Collectors.toList());
                System.out.println(pageUriList);
            }
        }
        return ResponseResult.okResult(null);
    }

    @Override
    public ResponseResult pageParseTest(CrawlNovelRequestDto dto) {
        // 访问分页目录地址
        String response = client.http(dto.getCatalogueUrl());
        List<String> pageUriList = null;
        List<ChapterLinkDto> contentLinkList = new ArrayList<>(1024);
        String prefix = dto.getPrefix();

        // 校验类型
        if (RESULT_TYPE_HTML.equals(dto.getResultType())) {
            Document pageDocument = Jsoup.parse(response);

            if (TRUE.equals(dto.getIsPaginate())) {
                //确定分页html范围
                StringBuilder pageSb = new StringBuilder(dto.getPageTag())
                        .append("[").append(dto.getPageAttribute())
                        .append("=").append(dto.getPageAttributeValue()).append("]");

                Elements firstPageDocument = pageDocument.select(pageSb.toString());
                Elements pageUrisElements = firstPageDocument.select("option");
                pageUriList = pageUrisElements.stream().map(pageLink -> {
                    return pageLink.attr("value");
                }).collect(Collectors.toList());

                pageUriList.stream().forEach(uri -> {
                    String url = prefix + uri;
                    String pageHtml = client.http(url);
                    Document chapterDocument = Jsoup.parse(pageHtml);

                    StringBuilder chapterSb = new StringBuilder(dto.getChapterTag())
                            .append("[").append(dto.getChapterAttribute())
                            .append("=").append(dto.getChapterAttributeValue()).append("]");
                    Elements chapterElements = chapterDocument.select(chapterSb.toString());

                    // TODO 需要确定链接？先默认为 a 标签
                    Elements chapterATag = chapterElements.select("a");
                    List<ChapterLinkDto> collect = chapterATag.stream().map(chapterLink -> {
                        // TODO 需要过滤无关链接
                        String title = chapterLink.attr("title");
                        String href = chapterLink.attr("href");
                        return new ChapterLinkDto(title, href);
                    }).collect(Collectors.toList());
                    contentLinkList.addAll(collect);
                });
            }
        }
        return ResponseResult.okResult(contentLinkList);
    }
}
